package com.weiiew.common.utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * img标签工具类
 *
 * @author zhangchao
 */
public final class ImgTagUtils {

    private static String trimTagStr(String tagStr, String tagName) {
        // 去掉标签结尾的/>，方便后面 src 属性的正则表达式。
        // 这样可以适应  <video src=http://www.yourhost.com/xxx/>  这样的标签
        if (tagStr.endsWith("/>")) {
            tagStr = tagStr.substring(0, tagStr.length() - 2);
            tagStr = tagStr + " ";
        }
        // 去掉标签结尾的>，方便后面匹配属性的正则表达式。
        // 这样可以适应  <video src=http://www.yourhost.com/xxx>  这样的标签
        else if (tagStr.endsWith(">")) {
            tagStr = tagStr.substring(0, tagStr.length() - 1);
            tagStr = tagStr + " ";
        }
        // 去掉字符串开头的 <video 或 <source
        tagStr = tagStr.substring(1 + tagName.length());
        tagStr = " " + tagStr;
        return tagStr;
    }

    /**
     * 从html代码中，获得指定标签的指定属性的取值
     *
     * @param html         HTML代码
     * @param tagName      指定的标签名称
     * @param propertyName 指定的属性名称
     * @return 查询到的值
     */
    public static List<String> listTagPropertyValue(final String html, final String tagName, final String propertyName) {
        // 结果集合
        ArrayList<String> result = new ArrayList<>();
        // 找出HTML代码中所有的tagName标签
        List<String> list = RegexUtils.getMatchList(html, "<" + tagName + "[^>]*>", true);
        // 循环遍历每个标签字符串，找出其中的属性字符串,比如 src=....
        for (String tagStr : list) {
            result.addAll(getProperties(trimTagStr(tagStr, tagName), propertyName));
        } // end for (String tagStr : list)
        result.trimToSize();
        return result;
    }


    /**
     * 从html代码中，获得所有指定标签的指定属性的第一个取值
     *
     * @param html          HTML代码
     * @param tagName       指定的标签名称
     * @param propertyNames 指定的属性名称列表
     * @return 查询到的值
     */
    public static List<Map<String, String>> listTagPropertiesFirstValue(final String html, final String tagName, final String[] propertyNames) {
        // 结果集合
        ArrayList<Map<String, String>> result = new ArrayList<>();
        // 找出HTML代码中所有的tagName标签
        List<String> list = RegexUtils.getMatchList(html, "<" + tagName + "[^>]*>", true);
        // 循环遍历每个标签字符串，找出其中的属性字符串,比如 src=....
        for (String tagStr : list) {
            Map<String, String> propMap = new HashMap<>();
            tagStr = trimTagStr(tagStr, tagName);
            for (String propertyName : propertyNames) {
                String property = getFirstProperties(tagStr, propertyName);
//                System.out.println("property = " + property);
                propMap.put(propertyName, property);
            }
            result.add(propMap);
        }
        result.trimToSize();
        return result;
    }

    /**
     * 获取标签的第一个满足要求的属性值
     *
     * @param tagStr       标签字符串
     * @param propertyName 属性值
     * @return 第一个属性值
     */
    private static String getFirstProperties(String tagStr, String propertyName) {
        // 取出属性的值
        String regSingleQuote = "^" + propertyName + "='[^']*'"; // 使用单引号
        String regDoubleQuote = "^" + propertyName + "=\"[^\"]*\""; // 使用双引号
        String reg = "^" + propertyName + "=[^\\s]*\\s"; // 不使用引号
        int index = 0;
        int length = tagStr.length();
        while (index <= length) {
            String subStr = tagStr.substring(index);
            // 单引号
            String str;
            if ((str = RegexUtils.getFirstMatch(subStr, regSingleQuote, true)) != null) {
                // 往后跳过已经匹配的字符串。
                index += str.length();
                String propStr = str;
                propStr = propStr.trim();
                // 删除属性值和多余引号
                propStr = propStr.substring(propertyName.length() + 2, propStr.length() - 1);
                // 结果中加入图片URL
                return propStr;
            }
            // 双引号
            else if ((str = RegexUtils.getFirstMatch(subStr, regDoubleQuote, true)) != null) {
                // 往后跳过已经匹配的字符串。
                index += str.length();
                String propStr = str;
                propStr = propStr.trim();
                // 删除属性值和多余引号
                propStr = propStr.substring(propertyName.length() + 2, propStr.length() - 1);
                // 结果中加入图片URL
                return propStr;
            }
            // 不使用引号
            else if ((str = RegexUtils.getFirstMatch(subStr, reg, true)) != null) {
                // 往后跳过已经匹配的字符串。
                index += str.length();
                String propStr = str;
                propStr = propStr.trim();
                // 去掉 src=
                propStr = propStr.substring(propertyName.length() + 1);
                // 结果中加入图片URL
                return propStr;
            }
            // 其他属性-单引号
            else if ((str = RegexUtils.getFirstMatch(subStr, "^[\\w|-]+='[^']*'", true)) != null) {
                // 往后跳过已经匹配的字符串。
                index += str.length();
            }
            // 其他属性-双引号
            else if ((str = RegexUtils.getFirstMatch(subStr, "^[\\w|-]+=\"[^\"]*\"", true)) != null) {
                // 往后跳过已经匹配的字符串。
                index += str.length();
            } else {
                index++;
            }
        }
        return null;
    }

    /**
     * 获取所有满足要求的属性值
     *
     * @param tagStr       标签字符串
     * @param propertyName 属性值
     * @return 所有满足要求的属性值
     */
    private static ArrayList<String> getProperties(String tagStr, String propertyName) {
        ArrayList<String> result = new ArrayList<>();
        // 取出属性的值
        String regSingleQuote = "^" + propertyName + "='[^']*'"; // 使用单引号
        String regDoubleQuote = "^" + propertyName + "=\"[^\"]*\""; // 使用双引号
        String reg = "^" + propertyName + "=[^\\s]*\\s"; // 不使用引号
        int index = 0;
        int length = tagStr.length();
        while (index <= length) {
            String subStr = tagStr.substring(index);
            // 单引号
            String str;
            if ((str = RegexUtils.getFirstMatch(subStr, regSingleQuote, true)) != null) {
                // 往后跳过已经匹配的字符串。
                index += str.length();
                String propStr = str;
                propStr = propStr.trim();
                // 删除属性值和多余引号
                propStr = propStr.substring(propertyName.length() + 2, propStr.length() - 1);
                // 结果中加入图片URL
                result.add(propStr);
            }
            // 双引号
            else if ((str = RegexUtils.getFirstMatch(subStr, regDoubleQuote, true)) != null) {
                // 往后跳过已经匹配的字符串。
                index += str.length();
                String propStr = str;
                propStr = propStr.trim();
                // 删除属性值和多余引号
                propStr = propStr.substring(propertyName.length() + 2, propStr.length() - 1);
                // 结果中加入图片URL
                result.add(propStr);
            }
            // 不使用引号
            else if ((str = RegexUtils.getFirstMatch(subStr, reg, true)) != null) {
                // 往后跳过已经匹配的字符串。
                index += str.length();
                String propStr = str;
                propStr = propStr.trim();
                // 去掉 src=
                propStr = propStr.substring(propertyName.length() + 1);
                // 结果中加入图片URL
                result.add(propStr);
            }
            // 其他属性-单引号
            else if ((str = RegexUtils.getFirstMatch(subStr, "^[\\w|-]+='[^']*'", true)) != null) {
                // 往后跳过已经匹配的字符串。
                index += str.length();
            }
            // 其他属性-双引号
            else if ((str = RegexUtils.getFirstMatch(subStr, "^[\\w|-]+=\"[^\"]*\"", true)) != null) {
                // 往后跳过已经匹配的字符串。
                index += str.length();
            } else {
                index++;
            }
        }
        return result;
    }

    /**
     * 从html代码中找出img标签的图片路径
     *
     * @param html HTML代码
     * @return 字符串列表，里面每个字符串都是图片链接地址
     */
    public static List<String> listImgSrc(final String html) {
        return listTagPropertyValue(html, "img", "src");
    }
}
